/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 * Description: atrace接口
 * Author: wuhaoyu
 * Create: 2025-02-10
 */

#include "dltrace_function.h"
#include "hccl_dl.h"
#include "log.h"

namespace hccl {

DlTraceFunction &DlTraceFunction::GetInstance()
{
    static DlTraceFunction hcclDlTraceFunction;
    return hcclDlTraceFunction;
}

DlTraceFunction::DlTraceFunction() : handle_(nullptr)
{
}

DlTraceFunction::~DlTraceFunction()
{
    if (handle_ != nullptr) {
        (void)HcclDlclose(handle_);
        handle_ = nullptr;
    }
}

HcclResult DlTraceFunction::DlTraceFunctionInterInit()
{
#ifndef CCL_KERNEL_AICPU
    dlAtraceDestroy = (void(*)(TraHandle handle))HcclDlsym(handle_, "AtraceDestroy");
    CHK_SMART_PTR_NULL(dlAtraceDestroy);
    dlAtraceSubmit = (HcclResult(*)(TraHandle handle, const void *buffer, u32 bufSize))HcclDlsym(handle_,
        "AtraceSubmit");
    CHK_SMART_PTR_NULL(dlAtraceSubmit);
    dlAtraceCreateWithAttr = (TraHandle(*)(int tracerType, const char *objName, const TraceAttr *attr))HcclDlsym(
        handle_, "AtraceCreateWithAttr");
    CHK_SMART_PTR_NULL(dlAtraceCreateWithAttr);
#else
    dlUtraceDestroy = (void(*)(TraHandle handle))HcclDlsym(handle_, "UtraceDestroy");
    CHK_SMART_PTR_NULL(dlUtraceDestroy);
    dlUtraceSubmit = (HcclResult(*)(TraHandle handle, const void *buffer, u32 bufSize))HcclDlsym(handle_, 
        "UtraceSubmit");
    CHK_SMART_PTR_NULL(dlUtraceSubmit);
    dlUtraceCreateWithAttr = (TraHandle(*)(int tracerType, const char *objName, const TraceAttr *attr))HcclDlsym(
        handle_, "UtraceCreateWithAttr");
    CHK_SMART_PTR_NULL(dlUtraceCreateWithAttr);
    dlUtraceSetGlobalAttr = (TraStatus(*)(const TraceGlobalAttr *attr))HcclDlsym(
        handle_, "UtraceSetGlobalAttr");
    CHK_SMART_PTR_NULL(dlUtraceSetGlobalAttr);
    dlUtraceSave = (TraStatus(*)(TracerType tracerType, bool syncFlag))HcclDlsym(handle_, "UtraceSave");
    CHK_SMART_PTR_NULL(dlUtraceSave);
#endif
    return HCCL_SUCCESS;
}

HcclResult DlTraceFunction::DlTraceFunctionInit()
{
    std::lock_guard<std::mutex> lock(handleMutex_);
    if (handle_ == nullptr) {
#ifndef CCL_KERNEL_AICPU
        handle_ = HcclDlopen("libascend_trace.so", RTLD_NOW);
        const char* errMsg = dlerror();
        CHK_PRT_RET(handle_ == nullptr, HCCL_ERROR("dlopen [%s] failed, %s", "libascend_trace.so",\
            (errMsg == nullptr) ? "please check the file exist or permission denied." : errMsg),\
            HCCL_E_OPEN_FILE_FAILURE);
#else
        handle_ = HcclDlopen("libutrace.so", RTLD_NOW);
        const char* errMsg = dlerror();
        CHK_PRT_RET(handle_ == nullptr, HCCL_ERROR("dlopen [%s] failed, %s", "libutrace.so",\
            (errMsg == nullptr) ? "please check the file exist or permission denied." : errMsg),\
            HCCL_E_OPEN_FILE_FAILURE);
#endif
    }
    CHK_RET(DlTraceFunctionInterInit());
    return HCCL_SUCCESS;
}
}
